package com.xmtlxx.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.common.utils.TreeBuildUtils;
import com.xmtlxx.wms.domain.StoreArea;
import com.xmtlxx.wms.domain.bo.StoreAreaBo;
import com.xmtlxx.wms.domain.vo.StoreAreaVo;
import com.xmtlxx.wms.mapper.StoreAreaMapper;
import com.xmtlxx.wms.service.IStoreAreaService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 库区Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class StoreAreaServiceImpl implements IStoreAreaService {

    private final StoreAreaMapper baseMapper;

    /**
     * 查询库区
     *
     * @param id 库区主键
     * @return 库区
     */
    @Override
    public StoreAreaVo queryById(String id){
        //return baseMapper.selectVoById(id);
        return baseMapper.selectStoreAreaVoByID(id);
    }

    /**
     * 查询库区列表
     *
     * @param bo 库区
     * @return 库区
     */
    @Override
    public TableDataInfo<StoreAreaVo> queryPageList(StoreAreaBo bo, PageQuery pageQuery) {
       // LambdaQueryWrapper<StoreArea> lqw = buildQueryWrapper(bo);
       // Page<StoreAreaVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Page<StoreAreaVo> result = baseMapper.selectPageStoreAreaList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询库区列表
     *
     * @param bo 库区
     * @return 库区
     */
    @Override
    public List<StoreAreaVo> queryList(StoreAreaBo bo) {
       // LambdaQueryWrapper<StoreArea> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectStoreAreaList(bo);
    }

    private LambdaQueryWrapper<StoreArea> buildQueryWrapper(StoreAreaBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<StoreArea> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getAno()), StoreArea::getAno, bo.getAno());
        lqw.eq(StringUtils.isNotBlank(bo.getStoreId()), StoreArea::getStoreId, bo.getStoreId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), StoreArea::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getLevels()), StoreArea::getLevels, bo.getLevels());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), StoreArea::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), StoreArea::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getParentId()), StoreArea::getParentId, bo.getParentId());
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), StoreArea::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增库区
     *
     * @param bo 库区
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(StoreAreaBo bo) {
        StoreArea add = BeanUtil.toBean(bo, StoreArea.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");
        if(!StringUtils.isEmpty(add.getParentId())){
            StoreArea info = baseMapper.selectById(add.getParentId());
            add.setAncestors(info.getAncestors()+ "," + add.getParentId());
        }else{
            add.setAncestors(add.getParentId());
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改库区
     *
     * @param bo 库区
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(StoreAreaBo bo) {
        StoreArea update = BeanUtil.toBean(bo, StoreArea.class);
        validEntityBeforeSave(update);
        if(!StringUtils.isEmpty(bo.getParentId())){
            StoreArea newParent = baseMapper.selectById(bo.getParentId());
            StoreArea oldClassify = baseMapper.selectById(bo.getId());
            if (ObjectUtil.isNotNull(newParent) && ObjectUtil.isNotNull(oldClassify)) {
                String newAncestors = newParent.getAncestors() + "," + newParent.getId();
                String oldAncestors = oldClassify.getAncestors();
                update.setAncestors(newAncestors);
                updateClassifyChildren(update.getId(), newAncestors, oldAncestors);
            }
        }
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 修改子元素关系
     *
     * @param id       被修改的分类ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateClassifyChildren(String id, String newAncestors, String oldAncestors) {
        List<StoreArea> children = baseMapper.selectList(new LambdaQueryWrapper<StoreArea>()
            .apply("find_in_set({0},ancestors)", id));
        for (StoreArea child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            baseMapper.updateStoreAreaChildren(children);
        }
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(StoreArea entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除库区
     *
     * @param ids 需要删除的库区主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<Tree<String>> buildStoreAreaTreeSelect(List<StoreAreaVo> items) {
        if (CollUtil.isEmpty(items)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(items, (storeArea, tree) ->
            tree.setId(storeArea.getId())
                .setParentId(storeArea.getParentId())
                .setName(storeArea.getName())
                .setWeight(storeArea.getId()));
    }
}
